<!--
 * @Author: zengwj
 * @Date: 2022-07-01 16:15:58
 * @LastEditors: zengwj
 * @LastEditTime: 2022-07-01 17:06:34
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    const FULFILLED = 'fulfilled'
    const REJECTED = 'rejected'
    const PENDING = 'pengding'
    class MyPromise {
      constructor(excutor) {
        excutor(this.resolve.bind(this), this.reject.bind(this))
      }
      status = PENDING
      result = null
      fulfilledCallbacks = []
      rejectdCallbacks = []
      resolve(value) {
        if (this.status === PENDING) {
          this.status = FULFILLED
          this.result = value
          this.fulfilledCallbacks.forEach(callback => {
            callback(value)
          })
        }
      }
      reject(reason) {
        if (this.status === PENDING) {
          this.status = REJECTED
          this.result = reason
          this.rejectdCallbacks.forEach(callback => {
            callback(reason)
          })
        }
      }
      then(fullfillFunc, rejectFunc) {
        return new MyPromise((resolve, reject) => {
          const fulfilledMicrotask = () => {
            queueMicrotask(() => {
              const x = fullfillFunc(this.result)
              resolve(x)
            })
          }
          const rejectedMicrotask = () => {
            queueMicrotask(() => {
              const x = rejectFunc(this.result)
              reject(x)
            })
          }
          if (this.status === PENDING) {
            this.fulfilledCallbacks.push(fulfilledMicrotask)
            this.rejectdCallbacks.push(rejectedMicrotask)
          } else if (this.status === FULFILLED) {
            fulfilledMicrotask()
          } else if (this.status === REJECTED) {
            rejectedMicrotask()
          }
        })

      }
      static all(promises) {
        return new MyPromise((resolve, reject) => {
          if (Array.isArray(promises)) {
            if (promises.length === 0) {
              this.resolve(promises)
            }
            const result = []
            let count = 0
            promises.forEach((promise, index) => {
              if (promise instanceof MyPromise) {
                promise.then((value) => {
                  result[index] = value
                  count++
                  count === promises.length && resolve(result)
                }, (reason) => {
                  reject(reason)
                })
              } else {
                result[index] = promise
                count++
                count === promises.length && resolve(result)
              }
            })
          } else {
            this.reject('fuck you,not array')
          }
        })

      }
      static resolve(value) {
        return new MyPromise((resolve) => {
          resolve(value)
        })
      }
    }
    new MyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve(1)
      }, 1000);
    }).then((value) => {
      console.log(value)
      return value + 1
    }).then((value) => {
      console.log(value)
    })
    const promise1 = MyPromise.resolve(3);
    const promise2 = 42;
    const promise3 = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        reject('foo')
      }, 100);
    })

    MyPromise.all([promise1, promise2, promise3]).then((values) => {
      console.log(values);
    }, (reason) => {
      console.log(reason)
    })
  </script>
</body>

</html>